var amqp = require('amqplib/callback_api');
var log4js = require('log4js');
var logger = log4js.getLogger('AMQChannel');

function AMQChannel(connection) {
    logger.trace('enter constructor');
    this.exchange = null;
    this.key = null;
    this.ch = null;
    this.amqConn = connection;
}

module.exports = AMQChannel;

AMQChannel.AMQChannel = AMQChannel;

AMQChannel.prototype.createExchange = function(exchange, key, cb) {
    logger.trace('enter createExchange');

    var exopts = {durable: false},
    that = this;

    this.exchange = exchange;
    this.key = key;
    if (this.amqConn !== null && this.amqConn.conn !== null) {
        logger.debug('create a channel');
        this.amqConn.conn.createChannel(function(err, ch) {
            if (err === null) {
                logger.debug('create or get an exchange: ' + exchange);
                ch.assertExchange(exchange, 'direct', exopts, function(err2, ok) {
                    if (err2 !== null) {
                        logger.error('cannot create the exchange: ' + exchange);
                        cb(err);
                    } else {
                        logger.debug('created exchange');
                        that.ch = ch;
                        cb(true);
                    }
                });
            } else {
                logger.error('cannot create a channel');
                cb(err);
            }
        });
    } else {
        logger.debug('connect to server before create exchange');
        cb({message: 'connect to server before create exchange'});
    }
};

AMQChannel.prototype.sendMessage = function(msg) {
    logger.trace('enter sendMessage');

    if (this.ch !== null) {
        logger.debug('send: ');
        logger.debug(msg);
        this.ch.publish(this.exchange, this.key, new Buffer(JSON.stringify(msg)));
    }
};

AMQChannel.prototype.bindQueue = function(name, qopts, consume, noAck, cb) {
    logger.trace('enter bindQueue');
    logger.debug('queue name: ' + name);

    var opts = qopts || {exclusive: true};
    var that = this;
    var qname = name || '';

    if (this.ch !== null) {
        logger.debug('create queue');
        this.ch.assertQueue(qname, opts, function(err, ok) {
            if (err !== null) {
                logger.error('cannot create queue');
                cb(err);
            } else {
                that.queue = ok.queue;
                logger.debug('queue created. bind the queue ' + that.queue +
                             ' to exchange "' + that.exchange + '" using key "' + that.key + '"');
                that.ch.bindQueue(that.queue, that.exchange, that.key, {}, function(error) {
                    if (error !== null) {
                        logger.error('cannot bind queue');
                        logger.error(error);
                        cb(error);
                    } else {
                        logger.debug('bind queue ok');
                        that.ch.consume(that.queue, consume, {noAck: noAck}, function(error2) {
                            if (error2 !== null) {
                                logger.error('cannot register a consume');
                                cb(error2);
                            } else {
                                logger.debug('register consume ok');
                                cb(true);
                            }
                        });
                    }
                });
            }
        });
    }
};

AMQChannel.prototype.disconnect = function(cb) {
    logger.trace('enter disconnect');
    if (this.ch !== null) {
        var that = this;
        this.ch.close(function() {
            that.ch = null;
            if (typeof cb === 'function') {
                cb();
            }
        });
    }
};
